package org.keyintegrity.webbeans.metadata;

import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.log4j.Logger;
import org.apache.tapestry.BaseComponent;
import org.keyintegrity.webbeans.metadata.store.MetadataStore;
import org.keyintegrity.webbeans.metadata.store.MetadataStoreContext;
import org.keyintegrity.webbeans.metadata.store.MetadataStoreException;
import org.keyintegrity.webbeans.metadata.store.MetadataStoreFactory;
import org.keyintegrity.webbeans.metadata.store.xmlstream.XmlStreamStoreContext;
import org.keyintegrity.webbeans.metadata.store.xmlstream.XmlStreamStoreContext.Scope;

public abstract class MetadataManager extends BaseComponent {

    private static final Logger logger = Logger.getLogger(MetadataManager.class); 
    
    private static MetadataStoreWrapper wrapper;
    private static MetadataStore webbeansCoreStore;

    /** Path to core metadata store xml-file in classpath */
    public static final String WEBBEANS_CORE_METADATA_XMLSTREAM = "org/keyintegrity/webbeans/metadata/store/xmlstream/";

    public static synchronized MetadataStore getWebbeansCoreStore() {
        if (webbeansCoreStore == null) {
            MetadataStoreContext context = new XmlStreamStoreContext(WEBBEANS_CORE_METADATA_XMLSTREAM, Scope.RUNTIME);
            webbeansCoreStore = MetadataStoreFactory.getMetadataStore(context);
            logger.info("Webbeans Core Metadata Store : " + webbeansCoreStore.getName());
        }
        return webbeansCoreStore;
    }
    
    public static FieldMetadata getFieldMetadata(Class clazz, final String fieldName) {
        BeanMetadata bm;
        try {
            //  FIXME Recognize user-defined stores
            throw new MetadataStoreException("FIXME Recognize user-defined stores");
        } catch (MetadataStoreException e) {
            //  Lookup webbeans core store
            try {
                bm = getWebbeansCoreStore().lookupBeanMetadataForClass(clazz);
                FieldMetadata fm = bm == null ? BeanMetadata.getDefaultFieldMetadata(fieldName) 
                        : bm.getMetadataForField(fieldName);
                return fm;
            } catch (MetadataStoreException e1) {
                throw new ApplicationRuntimeException(e1.getMessage(), e1);
            }
        }
    }

    public static synchronized MetadataStoreWrapper getWrapper() {
        if (wrapper == null) {
            wrapper = new MetadataStoreWrapper();
            wrapper.getMetadataStores().add(getWebbeansCoreStore());
        }
        return wrapper;
    }
    
    public static synchronized void registerStore(MetadataStore store) {
        if (! getWrapper().getMetadataStores().contains(store)) {
            getWrapper().getMetadataStores().add(store);
        }
    }

    public void updateMetadata(MetadataStore store) {
        try {
            for (BeanMetadata bm : store.getMetadataList()) {
                store.storeMetadata(bm);
            }
            //  TODO Handle ok
        } catch (MetadataStoreException e) {
            //  TODO Handle error
            throw new ApplicationRuntimeException(e.getMessage(), e);
        }
    }
}
